//! Copyright 2012 NTH Technology, Inc.
//! All rights reserved
//!
#include "stm32f10x.h"
#include "BoardHardware.h"
#include "Config.h"
#include "LedDriver.h"
#include "RF.h"

extern "C"  {
    volatile bool s_HaveAnEventFlag;
    volatile U16  v_TimeLow;
    volatile U16  v_TimeHigh;
    volatile U16  s_CaptureBaseTimer;
    void TIM3_IRQHandler(void)
    {
        if(TIM_GetITStatus(TIM3, TIM_IT_CC2) == RESET) return;

        /* Clear TIM3 Capture compare interrupt pending bit */
        TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);

        U16 captureTimer = TIM_GetCapture2(TIM3);
        U16 captureValue;
        if( captureTimer >= s_CaptureBaseTimer )
        {
            captureValue = captureTimer - s_CaptureBaseTimer;
        }
        else
        {
            captureValue = captureTimer + (~s_CaptureBaseTimer) + 1;
        }
        s_CaptureBaseTimer = captureTimer;

        if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_7) == Bit_SET) 
        {
            v_TimeLow = captureValue;
            s_HaveAnEventFlag = true;
        }
        else
        {
            v_TimeHigh = captureValue;
        }
    }
};

bool cRF::s_RFSysnBitTimeout;
U8 cRF::s_BitCnt;
U8 cRF::s_pRFBuff[3];
cSysTick cRF::s_RFTick;

void cRF::InitReset()
{
    /* TIM3 clock enable */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
    /* GPIOA and GPIOB clock enable */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    /* TIM3 channel 2 pin (PA.07) configuration */
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* Enable the TIM3 global Interrupt */
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    /* TIM3 configuration: Input Capture mode ---------------------
        The external signal is connected to TIM3 CH2 pin (PA.07)  
        The Rising edge is used as active edge,
        The TIM3 CCR2 is used to compute the frequency value 
    ------------------------------------------------------------ */
    TIM_ICInitTypeDef  TIM_ICInitStructure;
    TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
    TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_BothEdge;
    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
    TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
    TIM_ICInitStructure.TIM_ICFilter = 0x0;

    TIM_ICInit(TIM3, &TIM_ICInitStructure);
  
    /* TIM enable counter */
    TIM_Cmd(TIM3, ENABLE);

    /* Enable the CC2 Interrupt Request */
    TIM_ITConfig(TIM3, TIM_IT_CC2, ENABLE);

    s_HaveAnEventFlag = false;
    s_CaptureBaseTimer = 0;
    s_BitCnt = 0;
    s_RFSysnBitTimeout = false;

    s_RFTick.SetTimeout(TIMEOUT_RF);
    s_RFTick.ResetTimeBase();
}


bool cRF::CheckReceive()
{
    if(false == s_HaveAnEventFlag) return (false);
    s_HaveAnEventFlag = false;


    U16 timeHigh = v_TimeHigh;
    U16 timeLow = v_TimeLow;
    U8 byteIndex = (s_BitCnt>>3) & 0x03;
    U8 temp = s_pRFBuff[byteIndex]<<1;

    if ((timeHigh > timeLow) && (timeHigh < timeLow*6))
    {
        cLedDriver::InvLed();
        s_pRFBuff[byteIndex] = temp | 1;
    }
    else if ((timeLow > timeHigh) && (timeLow < timeHigh*6))
    {
        //cLedDriver::InvLed();
        s_pRFBuff[byteIndex] = temp;
    }
    else
    {
        //cLedDriver::InvLed();
        s_BitCnt = 0;
        return (false);
    }

    s_BitCnt++;
    if ((NUMBER_RF_BIT*2) <= s_BitCnt)
    {
        s_BitCnt = 0;
        return (true);
//         if(true == s_RFSysnBitTimeout)
//         {
//             s_RFSysnBitTimeout = false;
//             s_RFTick.ResetTimeBase();
//             return (true);
//         }
//         s_RFSysnBitTimeout = false;
//         s_RFTick.ResetTimeBase();
    }

    return (false);
}


void cRF::RunOne()
{
    if ( true == CheckReceive() )
    {
        //cLedDriver::InvLed();
    }
//     if( true == s_RFTick.CheckTimeOut())
//     {
//         s_RFSysnBitTimeout = true;
//     }
}

